//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<enumeration10.h>
///	@path	~/src/graphics/dx10/
///	@date	2007/09/19
///	@desc	Enumerates available Direct3D10 adapters, devices, modes, etc.

#pragma once

#include "xeres.h"

// DirectX 9 is also needed
#include <d3d9.h>

// DirectX 10 header files
#include <d3d10.h>

// STL
#include <vector>

#define DXGI_MAX_DEVICE_IDENTIFIER_STRING 128

namespace xeres {

	/*!
		\class	EnumOutputInfo10
		\brief
	*/
	class EnumOutputInfo10
	{
	public:
		/// \dtor
		~EnumOutputInfo10( void );

		// data
		UINT				m_adapterOrdinal;
		UINT				m_output;
		IDXGIOutput *		m_pOutput;
		DXGI_OUTPUT_DESC	m_desc;
		std::vector<DXGI_MODE_DESC> m_displayModeList;
	};

	/*!
		\class	EnumDeviceInfo10
		\brief
	*/
	class EnumDeviceInfo10
	{
	public:
		/// \dtor
		~EnumDeviceInfo10( void );

		// data
		UINT				m_adapterOrdinal;
		D3D10_DRIVER_TYPE	m_deviceType;
	};

	// forward declarations
	class EnumDeviceSettings10;

	/*!
		\class	EnumAdapterInfo10
		\brief	A class describing an adapter which contains
				a unique adapter ordinal that is installed on the system.
	*/
	class EnumAdapterInfo10
	{
	public:
		/// \dtor
		~EnumAdapterInfo10( void );

		// data
		UINT				m_adapterOrdinal;
		DXGI_ADAPTER_DESC	m_adapterDesc;
		WCHAR				m_uniqueDescription[DXGI_MAX_DEVICE_IDENTIFIER_STRING];
		IDXGIAdapter *		m_adapter;

		std::vector<EnumOutputInfo10*> m_outputInfoList;
		std::vector<EnumDeviceInfo10*> m_deviceInfoList;
		std::vector<EnumDeviceSettings10*> m_deviceSettingsList;
	};

	/*!
		\class	EnumDeviceSettings10
		\brief
	*/
	class EnumDeviceSettings10
	{
	public:
		UINT				m_adapterOrdinal;
		D3D10_DRIVER_TYPE	m_deviceType;
		DXGI_FORMAT			m_backBufferFormat;
		BOOL				m_windowed;
		UINT				m_output;

		std::vector<UINT>	m_multiSampleCountList;
		std::vector<UINT>	m_multiSampleQualityList;

		EnumAdapterInfo10 *	m_adapterInfo;
		EnumDeviceInfo10 *	m_deviceInfo;
		EnumOutputInfo10 *	m_outputInfo;
	};

	/*!
		\class	EnumD3D10
		\brief	Enumerates available Direct3D10 adapters, devices, modes, etc.
	*/
	class EnumD3D10
	{
	public:

		/*!
			\brief		Get the only instance of EnumD3D10
			\return		The instance.
		*/
		static EnumD3D10& instance( void );

		// initialize
		void Initialize( bool bEnumerateAllAdapterFormats );

		// finalize
		void Finalize( void );

		const std::vector<EnumAdapterInfo10*>& GetAdapterInfoList( void ) const;
		const EnumAdapterInfo10 * GetAdapterInfo( UINT AdapterOrdinal ) const;
		const EnumDeviceInfo10 * GetDeviceInfo( UINT AdapterOrdinal, D3D10_DRIVER_TYPE DeviceType ) const;
		const EnumOutputInfo10 * GetOutputInfo( UINT AdapterOrdinal, UINT Output ) const;
		const EnumDeviceSettings10 * GetDeviceSettings( UINT AdapterOrdinal, D3D10_DRIVER_TYPE DeviceType,
			UINT Output, DXGI_FORMAT BackBufferFormat, BOOL Windowed ) const;

	private:

		/// \ctor
		EnumD3D10( void );

		/// \dtor
		~EnumD3D10( void );

		// initialized tag
		bool m_inited;
		bool m_enumerateAllAdapterFormats;

		UINT m_minWidth;
		UINT m_maxWidth;
		UINT m_minHeight;
		UINT m_maxHeight;
		UINT m_refreshMin;
		UINT m_refreshMax;
		UINT m_multisampleQualityMax;

		std::vector<DXGI_FORMAT> m_depthStencilPossibleList;
		std::vector<EnumAdapterInfo10 *> m_adapterInfoList;

		void Enumerate( void );

		HRESULT EnumerateOutputs( EnumAdapterInfo10 * pAdapterInfo );
		HRESULT EnumerateDevices( EnumAdapterInfo10 * pAdapterInfo );
		HRESULT EnumerateDeviceSettings( IDXGIFactory * pFactory , EnumAdapterInfo10 * pAdapterInfo );
		HRESULT EnumerateDisplayModes( EnumOutputInfo10 * pOutputInfo );
		void BuildMultiSampleQualityList( IDXGIFactory * pFactory , DXGI_FORMAT fmt, EnumDeviceSettings10 * pDeviceCombo );
		void ClearAdapterInfoList();
	};

} // namespace xeres
